<template>
  <div class="editor-container">
    <div class="left-panel">
      <el-scrollbar>
        <el-affix position="top" :offset="60">
          <el-card class="command-card">
            <el-row>
              <el-col :span="12">
                <el-button size="large" :icon="Plus" type="primary" @click="showDialog">添加命令</el-button>
              </el-col>
              <el-col :span="12">
                <el-select clearable size="large" v-model="groupFilter" placeholder="过滤显示组别">
                  <el-option
                      v-for="item in commandGroupOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                </el-select>
              </el-col>
            </el-row>
          </el-card>
        </el-affix>
        <div v-for="(handler, index) in commandHandlers.filter(o => groupFilter ? getFirstValue(o.group) === groupFilter : true)" :key="index">
          <el-card v-if="!visible(index)" class="command-card" shadow="hover">
            <div class="card-header" @click="changeVisible(index)">
              <el-descriptions size="large" :column="2" border>
                <el-descriptions-item label="命令名称">{{ getFirstValue(handler.commandName) }}</el-descriptions-item>
                <el-descriptions-item label="描述">{{ getFirstValue(handler.description) }}</el-descriptions-item>
              </el-descriptions>
              <span style="color:grey">（点击展开）</span>
              <el-tag type="info">{{ getFirstValue(handler.group) }}</el-tag>
            </div>
          </el-card>
          <el-card v-else class="command-card" shadow="hover">
            <template #header>
              <div class="card-header" @click="changeVisible(index)">
                <span class="command-name">{{ getFirstValue(handler.commandName) }}</span>
                <el-input v-model="handler.group[0]" @click.stop style="width: 240px">
                  <template #prepend>
                    命令组
                  </template>
                </el-input>
              </div>
            </template>

            <div class="card-content">
              <el-row :gutter = "20">
                <el-col :span="8">
                  <div class="form-item">
                    <span class="label" style="font-weight: bolder;"><span style="color:red;">*</span>命令名称:</span>
                    <el-input v-model="handler.commandName[0]" @change="() => commandNameChange(handler)">
                      <template #prefix>
                        <el-icon><Cpu /></el-icon>
                      </template>
                    </el-input>
                  </div>
                </el-col>
                <el-col :span="8">
                  <div class="form-item">
                    <span class="label">视图类型:</span>
                    <el-input v-model="handler.viewType[0]" />
                  </div>
                </el-col>
                <el-col :span="8">
                  <div class="form-item">
                    <span class="label">别名:</span>
                    <el-input-tag v-model="handler.alias[0].string" placeholder="输入别名，回车创建">
                      <template #prefix>
                        <el-icon><Stamp /></el-icon>
                      </template>
                    </el-input-tag>
                  </div>
                </el-col>
              </el-row>

              <div class="form-item">
                <span class="label">描述:</span>
                <el-input v-model="handler.description[0]" autosize type="textarea" />
              </div>

              <div class="form-item">
                <span class="label" style="font-weight: bolder;"><span style="color:red;">*</span>Lua脚本:</span>
                <el-input
                    v-model="handler.lua[0]"
                    autosize
                    type="textarea"
                    :rows="4"
                    resize="vertical"
                    class="code-input"
                />
              </div>
            </div>
          </el-card>
        </div>
      </el-scrollbar>
    </div>
    <el-scrollbar class="right-panel">
      <el-card class="group-map-card">
        <template #header>
          <div class="table-header">命令组映射</div>
        </template>

        <el-table
            :data="commandGroupMap"
            border
            style="width: 100%"
            class="editable-table"
        >
          <el-table-column prop="group" label="命令组">
            <template #default="{ row }">
              <!--<el-input v-model="row._" />-->
              <el-select v-model="row._" class="key-select">
                <el-option
                    v-for="item in commandGroupOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>

          <el-table-column prop="key" label="设备类型">
            <template #default="{ row }">
              <el-select v-model="row.$.Key" class="key-select">
                <el-option
                    v-for="item in deviceOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>

          <el-table-column label="操作">
            <template #default="{ $index }">
              <el-button
                  type="danger"
                  :icon="Delete"
                  circle
                  @click="deleteGroupMapItem($index)"/>
            </template>
          </el-table-column>
        </el-table>

        <div class="table-actions">
          <el-button type="primary" @click="addNewGroupMapItem">添加映射</el-button>
        </div>
      </el-card>
      <el-card>
        <template #header>
          <el-button @click="convertToXml">生成xml</el-button>
        </template>
        <el-input type="textarea" autosize v-model="xml"/>
      </el-card>
    </el-scrollbar>
    <el-dialog v-model="dialogVisible" title="添加新命令">
      <el-row :gutter = "20">
        <el-col :span="6">
          <div class="form-item">
            <span class="label" style="font-weight: bolder;"><span style="color:red;">*</span>命令名称:</span>
            <el-input v-model="commandDefaultData.commandName[0]" @change="() => commandNameChange(commandDefaultData)" placeholder="命令名称，命令行终端中识别的符号">
              <template #prefix>
                <el-icon><Cpu /></el-icon>
              </template>
            </el-input>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="form-item">
            <span class="label">视图类型:</span>
            <el-input v-model="commandDefaultData.viewType[0]" placeholder="执行此命令的上下文前提"/>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="form-item">
            <span class="label">别名:</span>
            <el-input-tag v-model="commandDefaultData.alias[0].string" placeholder="输入别名，回车创建">
              <template #prefix>
                <el-icon><Stamp /></el-icon>
              </template>
            </el-input-tag>
          </div>
        </el-col>
        <el-col :span="6">
          <span class="label">命令组:</span>
          <el-input v-model="commandDefaultData.group[0]">
            <template #prefix>
              <el-icon><List /></el-icon>
            </template>
          </el-input>
        </el-col>
      </el-row>

      <div class="form-item">
        <span class="label">描述:</span>
        <el-input v-model="commandDefaultData.description[0]" autosize type="textarea" placeholder="关于此命令的描述"/>
      </div>

      <div class="form-item">
        <span class="label" style="font-weight: bolder;"><span style="color:red;">*</span>Lua脚本:</span>
        <el-input
            v-model="commandDefaultData.lua[0]"
            type="textarea"
            :rows="8"
            autosize
            resize="vertical"
            class="code-input"
            placeholder="Lua脚本（注意：函数名必须与命令相同，参数必须为params）"
        />
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">Cancel</el-button>
          <el-button type="primary" @click="dialogConfirm">
            Confirm
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

import xml2js from 'xml2js';
import {Cpu, Delete, List, Plus, Stamp} from "@element-plus/icons-vue";

// 初始化数据
const jsonData = reactive({
  "CommandData": {
    "commandHandlers": [
      {
        "CommandHandler": [
          {
            "commandName": [
              "test"
            ],
            "viewType": [
              "UserView"
            ],
            "description": [
              "test"
            ],
            "group": [
              "test_group"
            ],
            "alias": [
              {
                "string": [
                  "tes",
                  "t"
                ]
              }
            ],
            "lua": [
              "function test(params)\n    self.DebugLog(params.args[1])\n    error(\"test error\")\n    return 'test'\nend"
            ]
          },
          {
            "commandName": [
              "rename"
            ],
            "viewType": [
              "UserView"
            ],
            "description": [
              "rename"
            ],
            "group": [
              "test_group"
            ],
            "alias": [
              {
                "string": [
                  "r",
                  "ren"
                ]
              }
            ],
            "lua": [
              "function rename(params)\n    self.SetDeviceName(params.args[1])\n    return 'successful rename to: ' .. params.args[1]\nend"
            ]
          },
          {
            "commandName": [
              "setData"
            ],
            "viewType": [
              "UserView"
            ],
            "description": [
              "setData"
            ],
            "group": [
              "test_group"
            ],
            "alias": [
              {
                "string": [
                  "s",
                  "sd"
                ]
              }
            ],
            "lua": [
              "function setData(params)\n    self.SetData(params.args[1],params.args[2])\n    return 'successful setData'\nend"
            ]
          },
          {
            "commandName": [
              "command2"
            ],
            "viewType": [
              "UserView"
            ],
            "description": [
              "command"
            ],
            "group": [
              "test_group2"
            ],
            "alias": [
              {
                "string": [
                  "com",
                  "c"
                ]
              }
            ],
            "lua": [
              "function command2(params)\n    self.DebugLog(params.args[1])\n    return 'test'\nend"
            ]
          }
        ]
      }
    ],
    "commandGroupMap": [
      {
        "Item": [
          {
            "_": "test_group",
            "$": {
              "Key": "Router"
            }
          },
          {
            "_": "test_group",
            "$": {
              "Key": "Server"
            }
          },
          {
            "_": "test_group",
            "$": {
              "Key": "Switch"
            }
          },
          {
            "_": "test_group2",
            "$": {
              "Key": "Router"
            }
          }
        ]
      }
    ]
  }
})
const commandDefaultData = reactive({
  "commandName": [
    ""
  ],
  "viewType": [
    "UserView"
  ],
  "description": [
    ""
  ],
  "group": [
    ""
  ],
  "alias": [
    {
      "string": []
    }
  ],
  "lua": [""]
})
const visibleFlag = reactive([])
const xml = ref('')
const groupFilter = ref('')
const dialogVisible = ref(false)

// 处理数据格式
const commandHandlers = jsonData.CommandData.commandHandlers[0].CommandHandler
const commandGroupMap = jsonData.CommandData.commandGroupMap[0].Item

// 设备类型选项
const deviceOptions = [
  { value: 'Router', label: '路由器' },
  { value: 'Server', label: '服务器' },
  { value: 'Switch', label: '交换机' }
]
//命令组选项
const commandGroupOptions = computed(() => {
  return Array.from(new Set(commandHandlers.map(item => item.group[0])))
      .map(item => ({value:item, label:item}));
})
// 方法
const getFirstValue = (arr) => arr?.[0] || ''
const deleteGroupMapItem = (index) => commandGroupMap.splice(index, 1)
const addNewGroupMapItem = () => commandGroupMap.push({
  _: 'new_group',
  $: { Key: 'Router' }
})

const visible = (index) => {
  if(index > visibleFlag.length){
    visibleFlag.push(false);
  }
  return visibleFlag[index];
}
const changeVisible =(index) =>{
  visibleFlag[index] = !visibleFlag[index];
}
function showDialog() {
  initCommandData();
  dialogVisible.value = true;
}
function dialogConfirm() {
  commandHandlers.push(JSON.parse(JSON.stringify(commandDefaultData)));
  dialogVisible.value = false;
}
function initCommandData() {
  commandDefaultData.commandName[0] = "";
  commandDefaultData.viewType[0] = "UserView";
  commandDefaultData.description[0] = "";
  commandDefaultData.group[0] = "";
  commandDefaultData.alias[0].string = [];
  commandDefaultData.lua[0] = "";
}
function commandNameChange(obj) {
  if(obj.lua[0]){
    if(obj.lua[0].substring(0,8) === "function"){
      obj.lua[0] = obj.lua[0].replace(
          obj.lua[0].substring(0,obj.lua[0].indexOf('\n')),
          "function " + obj.commandName[0] + "(params)"
      )
    }
  }else{
    obj.lua[0] = "function " + obj.commandName[0] + "(params)\n    #函数体（使用params.args[]获得命令行中的参数，下标从1开始）\n    return 'Successfully executed'\nend"
  }
}
function convertToXml() {
  const builder = new xml2js.Builder();
  xml.value = builder.buildObject(jsonData)
}
</script>

<style scoped>
.editor-container {
  display: flex;
  height: calc(100vh - 100px);
  padding: 20px;
  //background: #f5f7fa;
  gap: 10px;
}

.left-panel {
  flex: 1;
  //max-width: 600px;
  overflow-y: auto;
  padding-right: 10px;
}

.right-panel {
  flex: 1;
  overflow-y: auto;
  padding-right: 15px;
}

.command-card {
  margin: 0 5px 15px 10px;
}


.card-header {
  display: flex;
  cursor: pointer;
  justify-content: space-between;
  align-items: center;
}

.command-name {
  font-size: 16px;
  font-weight: 600;
}

.form-item {
  margin-bottom: 12px;
}

.label {
  display: block;
  margin-bottom: 4px;
  color: #606266;
  font-size: 14px;
}

.code-input {
  font-family: Monaco, Consolas, monospace;
  font-size: 12px;
}

.editable-table {
  margin-top: 10px;
}

.table-actions {
  margin-top: 15px;
  text-align: right;
}

.key-select {
  width: 100%;
}

.table-header {
  font-size: 16px;
  font-weight: 600;
}
</style>